package gov.nist.healthcare.testframework.communication.soap.server;

import gov.nist.healthcare.core.MalformedMessageException;
import gov.nist.healthcare.core.message.HL7Message;
import gov.nist.healthcare.core.message.v3.HL7V3Message;
import gov.nist.healthcare.testframework.communication.HSV3Request;
import gov.nist.healthcare.testframework.communication.HSV3Response;
import gov.nist.healthcare.testframework.communication.WSAException;
import gov.nist.healthcare.testframework.communication.server.ServerThread;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.UUID;
import javax.xml.soap.SOAPException;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.impl.DefaultHttpServerConnection;
import org.apache.http.params.BasicHttpParams;
import org.apache.log4j.Logger;
import org.apache.xmlbeans.XmlException;
import org.xml.sax.SAXException;

public class SoapServerThread extends ServerThread {

    private static final Logger logger = Logger.getLogger(SoapServerThread.class.getName());
    private HSV3Request current_request;
    private HSV3Response current_response;

    private final String ACTION_PREFIX = "urn:hl7-org:v3";

    // private static final String WSA_FROM =
    // "http://pixpdq2010tests.nist.gov:8080/";
    private static String DEFAULT_ENDPOINT_REFERENCE = "http://www.w3.org/2005/08/addressing/anonymous";

    @Override
    public String encode(HL7Message message) {

        String toreturn = "";

        try {
            current_response = new HSV3Response((HL7V3Message) message);
            InetSocketAddress from = (InetSocketAddress) socket.getLocalSocketAddress();

            String wsaAction = ACTION_PREFIX + ":"
                    + ((HL7V3Message) message).getInteractionId();
            String messageid = "urn:uuid:" + UUID.randomUUID();

            // current_response.setWSATo(this.current_request.getWSAReplyTo());
            current_response.setWSATo(DEFAULT_ENDPOINT_REFERENCE);
            current_response.setWSAAction(wsaAction);
            current_response.setWSARelatesTo(current_request.getWSAMessageID());

            toreturn = current_response.getStringRepresentation();
            logger.debug("What I encoded: \n" + toreturn);
        } catch (SOAPException soapex) {
            logger.debug("Error parsing HL7V3Message into a SOAP object: \n"
                    + soapex.getMessage());
        } catch (SAXException saxex) {
            logger.debug("Error parsing the XML in the HL7V3Message: \n"
                    + saxex.getMessage());
        } catch (IOException ioexx) {
            logger.debug("IOException: " + ioexx);

        } catch (Exception e) {
            logger.debug("Failed during encode: " + e.getMessage());
        }

        return toreturn;
    }

    @Override
    public HL7Message getMessage() {
        HL7Message message = null;

        try {
            BasicHttpParams params = new BasicHttpParams();
            DefaultHttpServerConnection conn = new DefaultHttpServerConnection();
            conn.bind(socket, params);
            HttpRequest request = conn.receiveRequestHeader();

            // Check HTTP Protocol version
            if (!(request.getProtocolVersion().equals(
                    org.apache.http.HttpVersion.HTTP_1_1) || request.getProtocolVersion().equals(
                    org.apache.http.HttpVersion.HTTP_1_0))) {
                logger.debug("According to WS Basic Progile 1.1, R1141: A"
                        + " MESSAGE MUST be sent using either HTTP/1.1 or HTTP/1.0.\n"
                        + "Version detected: " + request.getProtocolVersion());
            }

            if (request instanceof HttpEntityEnclosingRequest) {
                conn.receiveRequestEntity((HttpEntityEnclosingRequest) request);
                current_request = new HSV3Request(
                        (HttpEntityEnclosingRequest) request);

                try {
                    if (current_request.isWSAValid()) {
                        logger.debug("WSA Header Correct");
                    }
                } catch (WSAException wse) {
                    logger.debug(wse.getMessage());
                }
                message = current_request.getV3payload();
                logger.debug("Received Request \n "
                        + current_request.getStringRepresentation());
                // logger.debug("To " + current_request.getWSATo());
                // logger.debug("From " + current_request.getWSAFrom());
                // logger.debug("ReplyTo " + current_request.getWSAReplyTo());
                // logger.debug("Action " + current_request.getWSAAction());
                // logger.debug("MessageID " +
                // current_request.getWSAMessageID());
                // logger.debug("RelatesTo" +
                // current_request.getWSARelatesTo());
            }
        } catch (HttpException http) {
            logger.debug("Exception when reading the HTTP connection", http);
        } catch (SOAPException soap) {
            logger.debug("Exception when parsing the SOAP message", soap);
        } catch (XmlException xml) {
            logger.debug("Exception when creating the HL7V3 message", xml);
        } catch (MalformedMessageException mme) {
            logger.debug("Exception when creating the HL7V3 message", mme);
        } catch (SAXException e) {
            logger.debug("Exception when creating the string rep of the incoming request");
        } catch (IOException ioe) {
            logger.debug("Exception when reading the input stream", ioe);
        }

        return message;
    }

    @Override
    public boolean getSecure() {
        return false;
    }

    @Override
    public ServerThread restart() {
        return new SoapServerThread();
    }

}
